#include "iniparser.h"
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
#include "log/zlog.hh"

using namespace Util;
using namespace std;

bool hasBrackets(const std::string& str) { return !str.empty() && str.front() == '{' && str.back() == '}'; }

class Util::IniParserImpl
{
public:
    boost::property_tree::ptree root;
    bool valid;
    bool set_flag;
};

bool IniParser::is_valid() { return (_impl && _impl->valid); }

IniParser::IniParser(const char* file)
{
    _impl = new Util::IniParserImpl();
    _path = file;
    try
    {
        boost::property_tree::ini_parser::read_ini(file, _impl->root);
    }
    catch (const boost::property_tree::ini_parser_error& e)
    {
        zlog()->warn("IniParser warn: {}", e.what());
        _impl->valid = false;
        return;
    }
    catch (...)
    {
        _impl->valid = false;
        return;
    }
    _impl->valid = true;
    _impl->set_flag = false;
}
IniParser::~IniParser()
{
    this->save_ini();
    delete _impl;
    _impl = nullptr;
}

int IniParser::get(string exp, int32_t& val, int32_t defaultVal)
{
    if (!is_valid())
    {
        val = defaultVal;
        return FILE_ERR;
    }
    try
    {
        val = _impl->root.get<int32_t>(exp);
    }
    catch (boost::property_tree::ptree_error& e)
    {
        val = defaultVal;
        string message = e.what();
        // zlog()->warn("IniParser warn:get{} {}", exp.c_str(), e.what());
        // printf(message.c_str());
        // printf("\n");
        // printf("compare ret :%d ", message.compare("conversion of data to type \"i\" failed"));
        if (!message.compare("conversion of data to type \"i\" failed"))
            return VALUE_TYPE_ERR;
        else
            return READ_ERR;
    }

    return 0;
}

int IniParser::get(string exp, int32_t& val, int32_t defaultVal, int32_t min, int32_t max)
{
    int ret = 0;
    ret = get(exp, val, defaultVal);
    if (ret != OK)
        return ret;
    if (val > max || val < min)
    {
        val = defaultVal;
        return VALUE_RANGE_ERR;
    }
    return ret;
}

int IniParser::get(std::string exp, std::vector<int32_t>& val, std::vector<int32_t> def, int32_t min, int32_t max)
{
    string valStr;
    if (!is_valid())
    {
        // val = def;
        val.assign(def.begin(), def.end());
        return FILE_ERR;
    }
    try
    {
        valStr = _impl->root.get<string>(exp);
    }
    catch (boost::property_tree::ptree_error& e)
    {
        // zlog()->warn("IniParser warn:get{} {}", exp.c_str(), e.what());
        val.assign(def.begin(), def.end());
        return READ_ERR;
    }
    std::vector<std::string> optList;
    if (!hasBrackets(valStr))
    {
        //val = def;
        val.assign(def.begin(), def.end());
        return INI_VECTOR_FORMAT_ERR;
    }

    // 去除大括号
    valStr.erase(0, valStr.find_first_not_of("{"));
    valStr.erase(valStr.find_last_not_of("}") + 1);
    // 使用逗号分隔解析
    boost::algorithm::split(optList, valStr, boost::algorithm::is_any_of(","));
    // optList = split(valStr, ',');

    //val = def;
    val.assign(def.begin(), def.end());
    int ret = 0;
    for (size_t i = 0; i < def.size() && i < optList.size(); i++)
    {
        try
        {
            int32_t v = std::stoi(optList[i]);
            if (v <= max && v >= min)
            {
                val[i] = v;
            }
            else
            {
                ret = VALUE_RANGE_ERR;
            }
        }
        catch (std::exception& e)
        {
            ret = VALUE_TYPE_ERR;
            continue;
        }
    }
    if (def.size() != optList.size())
    {
        return DEFAULT_LEN_NOT_MACTH;
    }
    return ret;
}

int IniParser::get(string exp, double& val, double defaultVal, double min, double max)
{
    if (!is_valid())
    {
        val = defaultVal;
        return FILE_ERR;
    }
    try
    {
        val = _impl->root.get<double>(exp);
    }
    catch (boost::property_tree::ptree_error& e)
    {
        val = defaultVal;
        string message = e.what();
        // zlog()->warn("IniParser warn:get{} {}", exp.c_str(), e.what());
        // printf("compare ret :%d ", message.compare("conversion of data to type \"i\" failed"));
        if (!message.compare("conversion of data to type \"d\" failed"))
            return VALUE_TYPE_ERR;
        else
            return READ_ERR;
    }
    if (val - max > 0.0000000001 || val - min < -0.0000000001)
    {
        printf("val:%f, min:%f, max:%f\n", val, min, max);
        val = defaultVal;
        return VALUE_RANGE_ERR;
    }

    return 0;
}

int IniParser::get(std::string exp, std::vector<double>& val, std::vector<double> def, double min, double max)
{
    string valStr;
    if (!is_valid())
    {
        //val = def;
        val.assign(def.begin(), def.end());
        return FILE_ERR;
    }
    try
    {
        valStr = _impl->root.get<string>(exp);
    }
    catch (boost::property_tree::ptree_error& e)
    {
        //val = def;
        // zlog()->warn("IniParser warn:get{} {}", exp.c_str(), e.what());
        val.assign(def.begin(), def.end());
        return READ_ERR;
    }
    std::vector<std::string> optList;
    if (!hasBrackets(valStr))
    {
        //val = def;
        val.assign(def.begin(), def.end());
        return INI_VECTOR_FORMAT_ERR;
    }

    // 去除大括号
    valStr.erase(0, valStr.find_first_not_of("{"));
    valStr.erase(valStr.find_last_not_of("}") + 1);
    // 使用逗号分隔解析
    boost::algorithm::split(optList, valStr, boost::algorithm::is_any_of(","));
    // optList = split(valStr, ',');

    //val = def;
    val.assign(def.begin(), def.end());
    int ret = 0;
    for (size_t i = 0; i < def.size() && i < optList.size(); i++)
    {
        try
        {
            double v = std::stod(optList[i]);
            if (v - max <= 0.0000000001 && v - min >= -0.0000000001)
            {
                val[i] = v;
            }
            else
            {
                ret = VALUE_RANGE_ERR;
            }
        }
        catch (std::exception& e)
        {
            ret = VALUE_TYPE_ERR;
            continue;
        }
    }
    if (def.size() != optList.size())
    {
        return DEFAULT_LEN_NOT_MACTH;
    }
    return ret;
}

int IniParser::get(string exp, bool& val, bool defaultVal)
{
    int ret = 0;
    int value = 0;
    ret = get(exp, value, (int)defaultVal);
    val = (bool)value;
    return ret;
}

int IniParser::get(std::string exp, std::vector<bool>& val, std::vector<bool> def)
{
    string valStr;
    if (!is_valid())
    {
        //val = def;
        val.assign(def.begin(), def.end());
        return FILE_ERR;
    }
    try
    {
        valStr = _impl->root.get<string>(exp);
    }
    catch (boost::property_tree::ptree_error& e)
    {
        //val = def;
        // zlog()->warn("IniParser warn:get{} {}", exp.c_str(), e.what());
        val.assign(def.begin(), def.end());
        return READ_ERR;
    }
    std::vector<std::string> optList;
    if (!hasBrackets(valStr))
    {
        //val = def;
        val.assign(def.begin(), def.end());
        return INI_VECTOR_FORMAT_ERR;
    }

    // 去除大括号
    valStr.erase(0, valStr.find_first_not_of("{"));
    valStr.erase(valStr.find_last_not_of("}") + 1);
    // 使用逗号分隔解析
    boost::algorithm::split(optList, valStr, boost::algorithm::is_any_of(","));
    // optList = split(valStr, ',');

    // val = def;
    val.assign(def.begin(), def.end());
    int ret = 0;
    for (size_t i = 0; i < def.size() && i < optList.size(); i++)
    {
        try
        {
            size_t format_ret;
            format_ret = optList[i].find_first_of(".");
            if (format_ret != string::npos)
            {
                ret = VALUE_TYPE_ERR;
                continue;
            }
            int32_t v = std::stoi(optList[i]);
            val[i] = v;
        }
        catch (std::exception& e)
        {
            ret = VALUE_TYPE_ERR;
            continue;
        }
    }
    if (def.size() != optList.size())
    {
        return DEFAULT_LEN_NOT_MACTH;
    }
    return ret;
}

int IniParser::get(std::string exp, std::string& val, std::string defaultVal)
{
    if (!is_valid())
    {
        val = defaultVal;
        return FILE_ERR;
    }
    try
    {
        auto v = _impl->root.get<string>(exp);
        val = v;
    }
    catch (boost::property_tree::ptree_error& e)
    {
        // zlog()->warn("IniParser warn:get{} {}", exp.c_str(), e.what());
        val = defaultVal;
        return READ_ERR;
    }

    return 0;
}

int IniParser::get(std::string exp, std::vector<string>& val, std::vector<string> def)
{
    string valStr;
    if (!is_valid())
    {
        //val = def;
        val.assign(def.begin(), def.end());
        return FILE_ERR;
    }
    try
    {
        valStr = _impl->root.get<string>(exp);
    }
    catch (boost::property_tree::ptree_error& e)
    {
        // zlog()->warn("IniParser warn:get{} {}", exp.c_str(), e.what());
        // val = def;
        val.assign(def.begin(), def.end());
        return READ_ERR;
    }
    std::vector<std::string> optList;
    if (!hasBrackets(valStr))
    {
        // val = def;
        val.assign(def.begin(), def.end());
        return INI_VECTOR_FORMAT_ERR;
    }

    // 去除大括号
    valStr.erase(0, valStr.find_first_not_of("{"));
    valStr.erase(valStr.find_last_not_of("}") + 1);
    // 使用逗号分隔解析
    boost::algorithm::split(optList, valStr, boost::algorithm::is_any_of(","));
    // optList = split(valStr, ',');

    // val = def;
    val.assign(def.begin(), def.end());

    for (size_t i = 0; i < def.size() && i < optList.size(); i++) { val[i] = optList[i]; }
    if (def.size() != optList.size())
    {
        return DEFAULT_LEN_NOT_MACTH;
    }
    return 0;
}

int IniParser::set(std::string exp, std::string val)
{
    if (this->_impl == nullptr)
    {
        return FILE_ERR;
    }
    try
    {
        this->_impl->root.put<string>(exp, val);
        //boost::property_tree::ini_parser::write_ini(this->_path, _impl->root);
    }
    catch (boost::property_tree::ptree_error& e)
    {
        return WRITE_ERR;
    }
    _impl->set_flag = true;
    return 0;
}

int IniParser::set(std::string exp, std::vector<string> val)
{
    if (this->_impl == nullptr)
    {
        return FILE_ERR;
    }
    std::string result = "{";
    // 遍历vector
    for (size_t i = 0; i < val.size(); ++i)
    {
        result += val[i];
        if (i < val.size() - 1)  // 如果不是最后一个元素，添加逗号和空格作为分隔符
        {
            result += ", ";
        }
    }
    result += "}";

    try
    {
        this->_impl->root.put<string>(exp, result);
        //boost::property_tree::ini_parser::write_ini(this->_path, _impl->root);
    }
    catch (boost::property_tree::ptree_error& e)
    {
        return WRITE_ERR;
    }
    _impl->set_flag = true;
    return 0;
}

int IniParser::set(string exp, int val)
{
    int ret = 0;
    string s_val = to_string(val);
    ret = this->set(exp, s_val);
    return ret;
}

int IniParser::set(string exp, bool val)
{
    int ret = 0;
    string s_val = to_string(val);
    ret = this->set(exp, s_val);
    return ret;
}

int IniParser::set(string exp, double val)
{
    int ret = 0;
    string s_val = to_string(val);
    ret = this->set(exp, s_val);
    return ret;
}

int IniParser::set(string exp, std::vector<int> vec_val)
{
    int ret = 0;
    std::vector<std::string> vecString;
    for (const auto& val : vec_val) { vecString.push_back(to_string(val)); }
    ret = this->set(exp, vecString);
    return ret;
}

int IniParser::set(string exp, std::vector<double> vec_val)
{
    int ret = 0;
    std::vector<std::string> vecString;
    for (const auto& val : vec_val) { vecString.push_back(to_string(val)); }
    ret = this->set(exp, vecString);
    return ret;
}

int IniParser::set(string exp, std::vector<bool> vec_val)
{
    int ret = 0;
    std::vector<std::string> vecString;
    for (const auto& val : vec_val) { vecString.push_back(to_string(val)); }
    ret = this->set(exp, vecString);
    return ret;
}

int IniParser::save_ini()
{
    if (this->_impl == nullptr)
    {
        return FILE_ERR;
    }
    if (_impl->set_flag == true)
    {
        _impl->set_flag = false;
        try
        {
            zlog()->info("[IniParser] save {}", this->path());
            boost::property_tree::ini_parser::write_ini(this->_path, _impl->root);
        }
        catch (boost::property_tree::ptree_error& e)
        {
            return WRITE_ERR;
        }
    }

    return 0;
}
